 package net.go176.backpack.core;
 
 import java.io.IOException;
 import java.util.ArrayList;
 import java.util.Collections;
 import java.util.EnumMap;
 import java.util.Iterator;
 import java.util.LinkedHashMap;
 import java.util.LinkedHashSet;
 import java.util.List;
 import java.util.Map;
 import java.util.Set;
 import java.util.concurrent.ConcurrentHashMap;
 import java.util.logging.Level;
 import net.go176.backpack.api.AccessorGroup;
import net.go176.backpack.api.IDataAccessor;
import net.go176.backpack.config.ConfigManager;
import net.go176.backpack.gui.OfflineInvHolder;
import net.go176.backpack.gui.OnlineInvHolder;
import net.go176.backpack.util.DataUtil;
import net.go176.backpack.Backpack;



 import net.go176.backpack.gui.InventoryType;



 import org.bukkit.entity.Player;
 import org.bukkit.plugin.Plugin;
 import org.bukkit.scheduler.BukkitTask;
 
 
 
 
 public class DataManager
 {
   private Backpack p;
   private ConfigManager cfgMan;
   private volatile Map<AccessorGroup, List<IDataAccessor>> dataAccessorsMap = new LinkedHashMap<>();
   private Map<String, PlayerStatus> playerStatusesMap = new ConcurrentHashMap<>();
   private Map<String, Map<String, Map<InventoryType, OfflineInvHolder>>> offlineHoldersMap = new ConcurrentHashMap<>();
   private BukkitTask autoSaver = null;
   private BukkitTask statusesReseter = null;
   
   public void resetTimer() {
     disableTimer();
     int asIntv = this.cfgMan.ops_g_AutoSave_Interval;
     if (asIntv > 0)
       this.autoSaver = this.p.getServer().getScheduler().runTaskTimer((Plugin)this.p, this.autoSaveTask, asIntv, asIntv); 
     int rsIntv = this.cfgMan.ops_adv_ResetStatusesInterval;
     if (rsIntv > 0)
       this.statusesReseter = this.p.getServer().getScheduler().runTaskTimerAsynchronously((Plugin)this.p, this.resetStatusesTask, rsIntv, rsIntv); 
   }
   
   public void disableTimer() {
     if (this.autoSaver != null) {
       this.autoSaver.cancel();
       this.autoSaver = null;
     } 
     if (this.statusesReseter != null) {
       this.statusesReseter.cancel();
       this.statusesReseter = null;
     } 
   }
   
   public class PlayerStatus
   {
     public final String playerName;
     private volatile String worldName;
     private Map<InventoryType, OnlineInvHolder> holders = Collections.synchronizedMap(new EnumMap<>(InventoryType.class));
     
     private PlayerStatus(Player player) {
       this.playerName = player.getName();
       this.worldName = player.getWorld().getName();
     }
     
     public String getWorld() {
       return this.worldName;
     }
     
     public OnlineInvHolder getOnlineHolder(InventoryType invType) {
       OnlineInvHolder holder = this.holders.get(invType);
       if (holder != null && holder.inv.getViewers().isEmpty()) {
         this.holders.remove(invType);
         holder = null;
       } 
       return holder;
     }
     
     public OnlineInvHolder getAbsoluteOnlineHolder(InventoryType invType) {
       OnlineInvHolder holder = this.holders.get(invType);
       if (holder == null) {
         Player player = DataManager.this.p.getServer().getPlayer(this.playerName);
         if (player != null) {
           holder = new OnlineInvHolder(DataManager.this.p.getServer(), invType, player);
           this.holders.put(invType, holder);
         } 
       } 
       return holder;
     }
   }
 
   
   private final Runnable autoSaveTask = new Runnable()
     {
       public void run()
       {
         if (DataManager.this.cfgMan.ops_g_AutoSave_LogInfo)
           DataManager.this.p.getLogger().info("Auto saving player data..."); 
         DataManager.this.saveAllPlayerData();
         if (DataManager.this.cfgMan.ops_g_AutoSave_LogInfo) {
           DataManager.this.p.getLogger().info("Player data auto saved");
         }
       }
     };
   
   private final Runnable resetStatusesTask = new Runnable()
     {
       public void run()
       {
         if (!DataManager.this.playerStatusesMap.isEmpty())
           synchronized (DataManager.this.playerStatusesMap) {
             Iterator<Map.Entry<String, DataManager.PlayerStatus>> it = DataManager.this.playerStatusesMap.entrySet().iterator();
             while (it.hasNext()) {
               Map.Entry<String, DataManager.PlayerStatus> entry = it.next();
               Player player = DataManager.this.p.getServer().getPlayer(entry.getKey());
               if (player == null) {
                 it.remove();
               }
             } 
           }  
         for (Player player : DataUtil.getOnlinePlayers()) {
           Map<InventoryType, OnlineInvHolder> onlinHolders = (DataManager.this.getAbsoluteStatus(player)).holders;
           if (!onlinHolders.isEmpty())
             synchronized (onlinHolders) {
               Iterator<Map.Entry<InventoryType, OnlineInvHolder>> it = onlinHolders.entrySet().iterator();
               while (it.hasNext()) {
                 Map.Entry<InventoryType, OnlineInvHolder> entry = it.next();
                 if (((OnlineInvHolder)entry.getValue()).inv.getViewers().isEmpty()) {
                   it.remove();
                 }
               } 
             }  
         } 
         DataManager.this.saveOfflineInvs();
       }
     };
 
   
   public DataManager(Backpack plugin) {
     this.p = plugin;
     this.cfgMan = this.p.getConfigManager();
     this.resetStatusesTask.run();
     resetTimer();
   }
   
   public Set<AccessorGroup> getAccessorGroupSet() {
     return new LinkedHashSet<>(this.dataAccessorsMap.keySet());
   }
   
   public void setupAccessorGroup(AccessorGroup group, List<IDataAccessor> accessorList) {
     this.dataAccessorsMap.put(group, accessorList);
   }
   
   public List<IDataAccessor> getAccessorList(String group) {
     return this.dataAccessorsMap.get(group);
   }
   
   public PlayerStatus getStatus(String playerName) {
     return this.playerStatusesMap.get(playerName);
   }
   
   public PlayerStatus getAbsoluteStatus(Player player) {
     PlayerStatus status;
     synchronized (this.playerStatusesMap) {
       status = this.playerStatusesMap.get(player.getName());
       if (status == null) {
         status = new PlayerStatus(player, null);
         this.playerStatusesMap.put(player.getName(), status);
       } 
     } 
     return status;
   }
   
   public List<PlayerStatus> getPlayerStatuses() {
     return new ArrayList<>(this.playerStatusesMap.values());
   }
   
   public OfflineInvHolder getOfflineHolder(String playerName, String worldName, InventoryType invType) {
     Map<String, Map<InventoryType, OfflineInvHolder>> holdersTotal = this.offlineHoldersMap.get(playerName);
     if (holdersTotal != null) {
       Map<InventoryType, OfflineInvHolder> holders = holdersTotal.get(this.cfgMan.getWorldLink(worldName));
       if (holders != null) {
         OfflineInvHolder holder = holders.get(invType);
         if (holder != null)
           return holder; 
       } 
     } 
     return null;
   }
   
   public void postOfflineHolder(OfflineInvHolder holder) {
     Map<String, Map<InventoryType, OfflineInvHolder>> holdersTotal = this.offlineHoldersMap.get(holder.playerName);
     if (holdersTotal == null) {
       holdersTotal = new ConcurrentHashMap<>();
       this.offlineHoldersMap.put(holder.playerName, holdersTotal);
     } 
     String link = this.cfgMan.getWorldLink(holder.worldName);
     Map<InventoryType, OfflineInvHolder> holders = holdersTotal.get(link);
     if (holders == null) {
       holders = new EnumMap<>(InventoryType.class);
       holdersTotal.put(link, holders);
     } 
     holders.put(holder.invType, holder);
   }
   
   public void onCloseOfflineInv(OfflineInvHolder holder) {
     Map<String, Map<InventoryType, OfflineInvHolder>> holdersTotal = this.offlineHoldersMap.get(holder.playerName);
     if (holdersTotal == null)
       return; 
     String link = this.cfgMan.getWorldLink(holder.worldName);
     Map<InventoryType, OfflineInvHolder> holders = holdersTotal.get(link);
     if (holders == null)
       return; 
     if (trySaving(holder))
       holders.remove(holder.invType); 
     if (holders.isEmpty())
       holdersTotal.remove(link); 
     if (holdersTotal.isEmpty())
       this.offlineHoldersMap.remove(holder.playerName); 
   }
   
   public boolean trySaving(OfflineInvHolder holder) {
     if (holder.inv.getViewers().isEmpty()) {
       try {
         saveOfflineInv(holder);
       } catch (IOException e) {
         this.p.getLogger().log(Level.SEVERE, "Error saving " + holder.invType.invName + " of " + holder.playerName + " in " + holder.worldName, e);
       } 
       return true;
     } 
     return false;
   }
   
   public void handleJoin(Player player) {
     String worldOld = this.cfgMan.getLogoutWorld(player.getName());
     updatePlayerWorld(player, worldOld, true, true);
   }
   
   public void handleQuit(Player player) {
     this.playerStatusesMap.remove(player.getName());
     String worldName = player.getWorld().getName();
     this.cfgMan.saveLogoutWorld(player);
     savePlayerData(player, this.cfgMan.getWorldLink(worldName));
   }
   
   public void handleWorldChange(Player player, boolean save, boolean load) {
     String worldOld = (getAbsoluteStatus(player)).worldName;
     updatePlayerWorld(player, worldOld, save, load);
   }
   
   public void updatePlayerWorld(final Player player, final String worldOld, final boolean save, final boolean load) {
     this.p.getServer().getScheduler().runTaskLater((Plugin)this.p, new Runnable()
         {
           public void run()
           {
             String world = player.getWorld().getName();
             (DataManager.this.getAbsoluteStatus(player)).worldName = world;
             if (worldOld == null || worldOld.equals(world))
               return; 
             DataManager.this.cfgMan.saveLogoutWorld(player);
             if ((!save && !load) || (DataManager.this.cfgMan.ops_g_AllowBypass && player.hasPermission("mybackpack.bypass")))
               return; 
             String link1 = DataManager.this.cfgMan.getWorldLink(worldOld);
             String link2 = DataManager.this.cfgMan.getWorldLink(world);
             if (link1.equals(link2))
               return; 
             if (save)
               DataManager.this.savePlayerData(player, link1); 
             if (load) {
               DataManager.this.loadPlayerData(player, link2);
             }
           }
         } (this.p.getConfigManager()).ops_adv_UpdatePlayerWorldDelay)
   }
   
   public void savePlayerData(Player player, String link) {
     Iterator<Map.Entry<AccessorGroup, List<IDataAccessor>>> it = this.dataAccessorsMap.entrySet().iterator();
     while (it.hasNext()) {
       Map.Entry<AccessorGroup, List<IDataAccessor>> entry = it.next();
       AccessorGroup group = entry.getKey();
       if (group == null || !group.OWNER.isEnabled()) {
         it.remove();
         continue;
       } 
       List<IDataAccessor> accessorList = entry.getValue();
       if (accessorList != null) {
         for (IDataAccessor accessor : accessorList) {
           String playerName = player.getName();
           try {
             accessor.saveData(accessor.getDataFile(link, playerName, true), player);
           } catch (Throwable t) {
             this.p.getLogger().log(Level.SEVERE, "<" + group.DISPLAYNAME + "> Error saving data of " + playerName + " at world link: " + link, t);
           } 
         } 
       }
     } 
   }
   
   public void loadPlayerData(Player player, String link) {
     Iterator<Map.Entry<AccessorGroup, List<IDataAccessor>>> it = this.dataAccessorsMap.entrySet().iterator();
     while (it.hasNext()) {
       Map.Entry<AccessorGroup, List<IDataAccessor>> entry = it.next();
       AccessorGroup group = entry.getKey();
       if (group == null || !group.OWNER.isEnabled()) {
         it.remove();
         continue;
       } 
       List<IDataAccessor> accessorList = entry.getValue();
       if (accessorList != null) {
         for (IDataAccessor accessor : accessorList) {
           String playerName = player.getName();
           try {
             accessor.loadData(accessor.getDataFile(link, playerName, false), player);
           } catch (IOException e) {
             this.p.getLogger().log(Level.SEVERE, "<" + group.DISPLAYNAME + "> Error loading data of " + playerName + " at world link: " + link, e);
           } 
         } 
       }
     } 
     PlayerStatus status = getStatus(player.getName());
     if (status == null)
       return; 
     Map<InventoryType, OnlineInvHolder> onlineHolders = status.holders;
     if (!onlineHolders.isEmpty()) {
       synchronized (onlineHolders) {
         for (Map.Entry<InventoryType, OnlineInvHolder> entry : onlineHolders.entrySet()) {
           OnlineInvHolder holder = entry.getValue();
           this.p.getCoreHelper().getDataHandlerGUI(holder.invType).readOnlineInv(holder.inv, holder.player);
         } 
       } 
     }
   }
   
   public void saveAllPlayerData() {
     for (Player player : DataUtil.getOnlinePlayers())
       savePlayerData(player, this.cfgMan.getWorldLink(player.getWorld().getName())); 
   }
   
   public void saveOfflineInv(OfflineInvHolder holder) throws IOException {
     MyDataHandlerGUI handler = this.p.getCoreHelper().getDataHandlerGUI(holder.invType);
     handler.onCloseOfflineInv(holder.inv, handler.getGUIDataFile(this.cfgMan.getWorldLink(holder.worldName), holder.playerName, true));
   }
   
   public void saveOfflineInvs() {
     if (this.offlineHoldersMap.isEmpty())
       return; 
     synchronized (this.offlineHoldersMap) {
       Iterator<Map.Entry<String, Map<String, Map<InventoryType, OfflineInvHolder>>>> it = this.offlineHoldersMap.entrySet().iterator();
       while (it.hasNext()) {
         Map.Entry<String, Map<String, Map<InventoryType, OfflineInvHolder>>> entry = it.next();
         Map<String, Map<InventoryType, OfflineInvHolder>> offlineHoldersTotal = entry.getValue();
         if (offlineHoldersTotal.isEmpty())
           continue; 
         synchronized (offlineHoldersTotal) {
           Iterator<Map.Entry<String, Map<InventoryType, OfflineInvHolder>>> it1 = offlineHoldersTotal.entrySet().iterator();
           while (it1.hasNext()) {
             Map.Entry<String, Map<InventoryType, OfflineInvHolder>> entry1 = it1.next();
             Map<InventoryType, OfflineInvHolder> offlineHolders = entry1.getValue();
             if (offlineHolders.isEmpty())
               continue; 
             synchronized (offlineHolders) {
               Iterator<Map.Entry<InventoryType, OfflineInvHolder>> it2 = offlineHolders.entrySet().iterator();
               while (it2.hasNext()) {
                 Map.Entry<InventoryType, OfflineInvHolder> entry2 = it2.next();
                 OfflineInvHolder holder = entry2.getValue();
                 try {
                   saveOfflineInv(holder);
                 } catch (IOException e) {
                   this.p.getLogger().log(Level.SEVERE, "Error saving " + holder.invType.invName + " of " + holder.playerName + " in " + holder.worldName, e);
                 } 
                 if (holder.inv.getViewers().isEmpty())
                   it2.remove(); 
               } 
               if (offlineHolders.isEmpty())
                 it1.remove(); 
             } 
           } 
           if (offlineHoldersTotal.isEmpty())
             it.remove(); 
         } 
       } 
     } 
   }
 }


/* Location:              D:\User\Xuan\Downloads\MyBackpack1.2.5.jar!\net\saralab\mybackpack\core\DataManager.class
 * Java compiler version: 7 (51.0)
 * JD-Core Version:       1.1.3
 */